/*
 *  Filename:lsv_volume.h
 *  Description:
 *
 *  Created on: 2017年3月2日
 *  Author: Asdf(825674301)
 */

#ifndef __LSV_VOLUME_H_
#define __LSV_VOLUME_H_

/** @file Volume模块
 *
 * 职责：
 * - 空间分配和回收（+批量方式）
 * - 写（+异步方式）
 * - 读（+异步方式）
 */

#include "lsv.h"
#include "lsv_conf.h"
#include "lsv_types.h"
#include "lsv_volume_proto.h"

typedef struct {
        lsv_u32_t chunk_id;
        lsv_u32_t offset;
        lsv_u32_t size;
        lsv_u8_t type;
} lsv_volume_io_t;

static inline void lsv_volume_io_init(lsv_volume_io_t *vio, lsv_u32_t chunk_id, lsv_u32_t offset, lsv_u32_t size,
                                      lsv_u8_t type) {
        vio->chunk_id = chunk_id;
        vio->offset = offset;
        vio->size = size;
        vio->type = type;
}

typedef void (*lsv_volume_chunk_rw_callback)(lsv_s32_t rw_rc, void*arg);

typedef struct {
        lsv_volume_proto_t *lsv_info;
        lsv_volume_io_t *vio;
        lsv_s8_t *buf;
        lsv_volume_chunk_rw_callback callback;
        void* callback_arg;
        lsv_u8_t is_free;
} lsv_volume_chunk_rw_callback_ctx;

// fill ino and storage_info
int lsv_volume_init(lsv_volume_proto_t *lsv_info, lsv_u32_t flag);

int lsv_volume_create(lsv_volume_proto_t *lsv_info);

int lsv_volume_delete(lsv_volume_proto_t *lsv_info);

int lsv_volume_flush(lsv_volume_proto_t *lsv_info);

int lsv_volume_load(lsv_volume_proto_t *lsv_info);

int lsv_volume_recovery(lsv_volume_proto_t *lsv_info);

int lsv_volume_chunk_malloc(lsv_volume_proto_t *lsv_info, lsv_u8_t type, lsv_u32_t *chunk_id);

int lsv_volume_chunk_free(lsv_volume_proto_t *lsv_info, lsv_u8_t type, lsv_u32_t chunk_id);

int lsv_volume_chunk_malloc_batch(lsv_volume_proto_t *lsv_info, lsv_u8_t type, lsv_u32_t count, lsv_u32_t *chunk_id);

int lsv_volume_chunk_free_batch(lsv_volume_proto_t *lsv_info, lsv_u8_t type, lsv_u32_t count, lsv_u32_t *chunk_id);

/**
 * @param offset offset of chunk
 * @param size buf size
 */
int lsv_volume_chunk_update(lsv_volume_proto_t *lsv_info, lsv_volume_io_t *vio, lsv_s8_t *buf);

/**
 * @brief 分配，并写入一个chunk
 *
 * @param lsv_info
 * @param buf
 * @param type
 * @param chunk_id
 * @return
 */
int lsv_volume_chunk_write(lsv_volume_proto_t *lsv_info, lsv_s8_t *buf, lsv_u8_t type, lsv_u32_t *chunk_id);

int lsv_volume_chunk_update_callback(lsv_volume_proto_t *lsv_info, lsv_volume_io_t *vio, lsv_s8_t *buf,
                                     lsv_volume_chunk_rw_callback callback, void* callback_arg);

int lsv_volume_chunk_read_data(lsv_volume_proto_t *lsv_info, uint64_t ino, lsv_u32_t chunk_id, lsv_u32_t offset,
                lsv_u32_t size, lsv_s8_t *buf);

int lsv_volume_chunk_read_data_i(lsv_volume_proto_t *lsv_info, lsv_io_t *io, lsv_s8_t *buf);

/**
 * @brief 读取一个chunk
 *
 * @param lsv_info
 * @param chunk_id
 * @param buf
 * @return
 */
int lsv_volume_chunk_read(lsv_volume_proto_t *lsv_info, lsv_u32_t chunk_id, lsv_s8_t *buf);

int lsv_volume_chunk_read_callback(lsv_volume_proto_t *lsv_info, lsv_volume_io_t *vio, lsv_s8_t *buf,
                lsv_volume_chunk_rw_callback callback, void* callback_arg) ;


typedef struct __chunk_pool {
        lsv_volume_proto_t *lsv_info;
        int capacity;
        int count;
        uint32_t *chunk_ids;
        lsv_rwlock_t lock;
} chunk_pool;

/**
 * @sa lsv_volume_pool.c
 *
 * @param _pool
 * @param lsv_info
 * @param count
 * @return
 */
int chunk_pool_init(chunk_pool **_pool, lsv_volume_proto_t *lsv_info, int count);

int chunk_pool_select(chunk_pool *pool, uint32_t *chunk_id);


                
#endif /* __LSV_VOLUME_H_ */
